#include <mainwindow.h>
#include <main.hpp>
#include <data_struct.h>

#include <QtWidgets/QApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QtGui/QFont>
#include <QtGui/QFontDatabase>
#include <task_manager.h>
#include <inference_engine.hpp>
#include <task_manager.h>
#include <ext_list.hpp>

int main(int argc, char *argv[]) {
    // ------------------------------ Parsing and validation of input args ---------------------------------
    if (!ParseAndCheckCommandLine(argc, argv)) {
        return 0;
    }
    try {
        cv::FileStorage fsread;
        if (FLAGS_c.empty()) {
            if (!fsread.open("config.xml", cv::FileStorage::READ)) {
                slog::err << "Can not open config.xml" << slog::endl;
                exit(-1);
            }
        } else {
            if (!fsread.open(FLAGS_c, cv::FileStorage::READ)) {
                slog::err << "No such file to open" << slog::endl;
                exit(-1);
            }
        }
        /** Get Device Config **/
        std::string device = fsread["device"];

        /** Get Camera Config **/
        cv::FileNode camera_node = fsread["camera"];

        std::vector<camera_t> cameras;
        camera_t camera_front;
        cv::FileNode camera_front_node = camera_node["camera-1"];
        camera_front.index = (int) camera_front_node["index"];
        camera_front.fps = (int) camera_front_node["fps"];
        camera_front.type = (MOBILESEARCH_CAMERA_TYPE) camera_front_node["type"];
        camera_front.message_queue = (std::string) camera_front_node["message_queue"];
        cameras.push_back(camera_front);

        camera_t camera_back;
        cv::FileNode camera_back_node = camera_node["camera-2"];
        camera_back.index = (int) camera_back_node["index"];
        camera_back.fps = (int) camera_back_node["fps"];
        camera_back.type = (MOBILESEARCH_CAMERA_TYPE) camera_back_node["type"];
        camera_back.message_queue = (std::string) camera_back_node["message_queue"];
        cameras.push_back(camera_back);

        /** Get Model Config **/
        cv::FileNode model_node = fsread["model"];
        std::string license_plate_recognition_barrier = model_node["license-plate-recognition-barrier"];
        std::string vehicle_attributes_recognition_barrier = model_node["vehicle-attributes-recognition-barrier"];
        std::string vehicle_license_plate_detection_barrier = model_node["vehicle-license-plate-detection-barrier"];
        std::string road_segmentation_adas = model_node["road-segmentation-adas"];
        std::string single_image_super_resolution = model_node["single-image-super-resolution"];


        InferenceEngine::Core ie;
        /** Loading default extensions **/
        if (device.find("CPU") != std::string::npos) {
            ie.AddExtension(std::make_shared<InferenceEngine::Extensions::Cpu::CpuExtensions>(), "CPU");
        }
        /** Printing device version **/
        slog::info << "Device info" << slog::endl;
        slog::info << ie.GetVersions(device) << slog::endl;
        ie.AddExtension(std::make_shared<InferenceEngine::Extensions::Cpu::CpuExtensions>(), "CPU");

        slog::info << "Loading network files" << slog::endl;

        InferenceEngine::CNNNetReader road_networkReader;
        /** Read Road network model **/
        road_networkReader.ReadNetwork(road_segmentation_adas);

        /** Extract model name and load weights **/
        std::string binFileName = fileNameNoExt(road_segmentation_adas) + ".bin";
        slog::info << road_segmentation_adas << slog::endl;
        slog::info << binFileName << slog::endl;
        road_networkReader.ReadWeights(binFileName);
        InferenceEngine::CNNNetwork network = road_networkReader.getNetwork();

        // -----------------------------------------------------------------------------------------------------

        // --------------------------- 3. Configure input & output ---------------------------------------------

        // --------------------------- Prepare input blobs -----------------------------------------------------
        slog::info << "Preparing input blobs" << slog::endl;

        /** Taking information about all topology inputs **/
        InferenceEngine::InputsDataMap inputInfo(network.getInputsInfo());
        /** Stores all input blobs data **/
        InferenceEngine::BlobMap inputBlobs;

        if (inputInfo.size() != 1) throw std::logic_error("Demo supports topologies only with 1 input");
        auto inputInfoItem = *inputInfo.begin();

        QApplication app(argc, argv);
        MainWindow window;
        window.setConfig(cameras);
        window.show();

        return QApplication::exec();
    } catch (cv::Exception &e) {
        slog::err << "Read config file error" << slog::endl;
    } catch (InferenceEngine::details::InferenceEngineException &e) {
        slog::err << "Read model file error" << slog::endl;
    }


//
}
